﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Runtime.Serialization;
using System.Text;
using FarseerPhysics;
using FarseerPhysics.Collision.Shapes;
using FarseerPhysics.Common;
using FarseerPhysics.Dynamics;
using FarseerPhysics.Dynamics.Joints;
using FarseerPhysics.Factories;
using Microsoft.Xna.Framework;
using SFML.Graphics;
using SFML.Window;
using Theta;
using Theta.Animations;
using Theta.Components;
using Theta.Entities;
using Theta.Input;
using Theta.Physics;
using Theta.Serialization;

namespace SFML_Testbed
{
    public class Spider
    {
        const float SpiderBodyRadius = 0.65f;
        bool _kneeFlexed;
        float _kneeTargetAngle = -0.4f;
        AngleJoint _leftKneeAngleJoint;
        AngleJoint _leftShoulderAngleJoint;
        Sprite _lowerLeg;
        Vector2 _lowerLegSize = new Vector2(1.8f, 0.3f);

        AngleJoint _rightKneeAngleJoint;
        AngleJoint _rightShoulderAngleJoint;
        float _s;
        bool _shoulderFlexed;
        float _shoulderTargetAngle = -0.2f;
        Sprite _torso;
        Sprite _upperLeg;
        Vector2 _upperLegSize = new Vector2(1.8f, 0.3f);

        Body _circle;
        Body _leftLower;
        Body _leftUpper;
        Body _rightLower;
        Body _rightUpper;

        public Spider(World world, Vector2 position)
        {
            //Load bodies
            _circle = BodyFactory.CreateCircle(world, SpiderBodyRadius, 0.1f, position);
            _circle.BodyType = BodyType.Dynamic;

            //Left upper leg
            _leftUpper = BodyFactory.CreateRectangle(world, _upperLegSize.X, _upperLegSize.Y, 0.1f,
                                                     _circle.Position - new Vector2(SpiderBodyRadius, 0f) -
                                                     new Vector2(_upperLegSize.X / 2f, 0f));
            _leftUpper.BodyType = BodyType.Dynamic;

            //Left lower leg
            _leftLower = BodyFactory.CreateRectangle(world, _lowerLegSize.X, _lowerLegSize.Y, 0.1f,
                                                     _circle.Position - new Vector2(SpiderBodyRadius, 0f) -
                                                     new Vector2(_upperLegSize.X, 0f) -
                                                     new Vector2(_lowerLegSize.X / 2f, 0f));
            _leftLower.BodyType = BodyType.Dynamic;

            //Right upper leg
            _rightUpper = BodyFactory.CreateRectangle(world, _upperLegSize.X, _upperLegSize.Y, 0.1f,
                                                      _circle.Position + new Vector2(SpiderBodyRadius, 0f) +
                                                      new Vector2(_upperLegSize.X / 2f, 0f));
            _rightUpper.BodyType = BodyType.Dynamic;

            //Right lower leg
            _rightLower = BodyFactory.CreateRectangle(world, _lowerLegSize.X, _lowerLegSize.Y, 0.1f,
                                                      _circle.Position + new Vector2(SpiderBodyRadius, 0f) +
                                                      new Vector2(_upperLegSize.X, 0f) +
                                                      new Vector2(_lowerLegSize.X / 2f, 0f));
            _rightLower.BodyType = BodyType.Dynamic;

            //Create joints
            JointFactory.CreateRevoluteJoint(world, _circle, _leftUpper, new Vector2(_upperLegSize.X / 2f, 0f));
            _leftShoulderAngleJoint = JointFactory.CreateAngleJoint(world, _circle, _leftUpper);
            _leftShoulderAngleJoint.MaxImpulse = 3f;

            JointFactory.CreateRevoluteJoint(world, _circle, _rightUpper, new Vector2(-_upperLegSize.X / 2f, 0f));
            _rightShoulderAngleJoint = JointFactory.CreateAngleJoint(world, _circle, _rightUpper);
            _rightShoulderAngleJoint.MaxImpulse = 3f;

            JointFactory.CreateRevoluteJoint(world, _leftUpper, _leftLower, new Vector2(_lowerLegSize.X / 2f, 0f));
            _leftKneeAngleJoint = JointFactory.CreateAngleJoint(world, _leftUpper, _leftLower);
            _leftKneeAngleJoint.MaxImpulse = 3f;

            JointFactory.CreateRevoluteJoint(world, _rightUpper, _rightLower, new Vector2(-_lowerLegSize.X / 2f, 0f));
            _rightKneeAngleJoint = JointFactory.CreateAngleJoint(world, _rightUpper, _rightLower);
            _rightKneeAngleJoint.MaxImpulse = 3;
        }

        public void Update(TimeSpan gameTime)
        {
            _s += (float)gameTime.TotalMilliseconds;
            if(_s > 4000)
            {
                _s = 0;

                _kneeFlexed = !_kneeFlexed;
                _shoulderFlexed = !_shoulderFlexed;

                if(_kneeFlexed)
                    _kneeTargetAngle = -1.4f;
                else
                    _kneeTargetAngle = -0.4f;

                if(_kneeFlexed)
                    _shoulderTargetAngle = -1.2f;
                else
                    _shoulderTargetAngle = -0.2f;
            }

            _leftKneeAngleJoint.TargetAngle = _kneeTargetAngle;
            _rightKneeAngleJoint.TargetAngle = -_kneeTargetAngle;

            _leftShoulderAngleJoint.TargetAngle = _shoulderTargetAngle;
            _rightShoulderAngleJoint.TargetAngle = -_shoulderTargetAngle;
        }
    }

    internal class Game : ThetaGame
    {
        Spider s;
        ThetaDebugView dv;
        //Random rand;
        //Animation anim;
        //AnimatedSprite spr;


        public override void Initialize()
        {
            //Todo: Write some nice description for the repo. Also use the Theta logo.
            base.Initialize();

            /*Frame[] frames = new Frame[4];
            frames[0] = new Frame(new Vector2i(0, 0), 0.1);
            frames[1] = new Frame(new Vector2i(32, 0), 0.1);
            frames[2] = new Frame(new Vector2i(64, 0), 0.1);
            frames[3] = new Frame(new Vector2i(96, 0), 0.1);
            Animation defaultAnim = new Animation(new[] { frames[2], frames[3] }, new Vector2i(32, 32), true);
            anim = new Animation(new[] { frames[0], frames[1] }, new Vector2i(32, 32), true);

            spr = new AnimatedSprite(new Image(@"Content\colorSheet.png"));
            spr.DefaultAnimation = defaultAnim;

            AddEntity(spr);
             */

            Core.RenderWindow.SetFramerateLimit(60);

            Converter.PixelsInMeter = 30f;

            float width = Converter.ToMeters(Core.WindowSize.X / 2f);
            float height = Converter.ToMeters(Core.WindowSize.Y / 2f + 50);
            float one = Converter.ToMeters(3);
            Vertices borders = new Vertices(4);
            borders.Add(new Vector2(one, height));
            borders.Add(new Vector2(width, height));
            borders.Add(new Vector2(width, one));
            borders.Add(new Vector2(one, one));

            Body b = BodyFactory.CreateLoopShape(Physics.World, borders);
            
            Body ball = BodyFactory.CreateCircle(Physics.World, Converter.ToMeters(50f / 2f), 1f, Converter.ToMeters(new Vector2(100, 250)));
            ball.BodyType = BodyType.Dynamic;
            
            s = new Spider(Physics.World, Converter.ToMeters(new Vector2(200, 20)));

            //Body edge = BodyFactory.CreateEdge(Physics.World, Converter.ToMeters(new Vector2(50f, 50f)),
              //                                 Converter.ToMeters(new Vector2(100, 100)));
            //edge.BodyType = BodyType.Dynamic;

            Physics.Gravity = new Vector2(0, 0.2f);

            dv = new ThetaDebugView(Physics.World);
            dv.AppendFlags(DebugViewFlags.Joint);
            dv.AppendFlags(DebugViewFlags.DebugPanel);
            dv.AppendFlags(DebugViewFlags.AABB);
            dv.AppendFlags(DebugViewFlags.CenterOfMass);
            dv.AppendFlags(DebugViewFlags.PerformanceGraph);
        }

        public override void Update(TimeSpan elapsedTime)
        {
            base.Update(elapsedTime);
            s.Update(elapsedTime);

            //var c = Core.ClearColor;


            /*if(KeyBoard.IsKeyDown(Keyboard.Key.Space))
            {
                spr.PlayAnimation(anim);
            }
            if (KeyBoard.IsKeyDown(Keyboard.Key.S))
            {
                anim.Loop = !anim.Loop;
            }*/
        }

        public override void Draw(RenderWindow renderWindow)
        {
            base.Draw(renderWindow);
            dv.Draw(renderWindow);
        }

        public override void Dispose()
        {
            base.Dispose();
        }
    }
}